package com.xbai.file.util;

import com.xbai.file.dto.FastDFSFile;
import lombok.extern.slf4j.Slf4j;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;
import org.springframework.core.io.ClassPathResource;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;


/**
 * @author jxbai
 * @desc 文件存储路径, 虚拟磁盘路径/数据两级目录/文件名例如：M00/00/00/wKjThF0DBzaAP23MAAXz2mMp9oM26.jpeg
 * 虚拟磁盘路径: 配置的虚拟路径，与磁盘选项store_path*对应。如果配置了store_path0 则是 M00，如果配置了 store_path1 则是 M01，以此类推。
 * 数据两级目录：storage 服务器在每个虚拟磁盘路径下创建的两级目录，用于存储数据文件。
 * 文件名：与文件上传时不同。是由存储服务器根据特定信息生成，文件名包含：源存储服务器 IP 地址、文件创建时间戳、文件大小、随机数和文件拓展名等信息。
 * @date 2021/1/27 0027
 */
@Slf4j
public class FastDFSClient {

    /*
     * 初始化tracker信息
     */
    static {
        // 获取tracker的配置文件fdfs_client.conf的位置
        String path = new ClassPathResource("fdfs_client.conf").getPath();
        try {
            //加载tracker配置信息
            ClientGlobal.init(path);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 文件上传
     *
     * @param file {@link FastDFSFile}
     * @return {@link String[]} 1:文件上传所存储的组名 2:文件存储路径,例如：M00/00/00/wKjThF0DBzaAP23MAAXz2mMp9oM26.jpeg
     */
    public static String[] upload(FastDFSFile file) {
        try {
            //获取StorageClient对象
            StorageClient storageClient = getStorageClient();
            //参数1 字节数组
            //参数2 扩展名(不带点)
            //参数3 元数据( 文件的大小,文件的作者,文件的创建时间戳)
            NameValuePair[] metaList = new NameValuePair[]{new NameValuePair(file.getAuthor()), new NameValuePair(file.getName())};

            // strings[0]==文件上传所存储的组名，例如:group1  strings[1]=文件存储路径,例如：M00/00/00/wKjThF0DBzaAP23MAAXz2mMp9oM26.jpeg
            // 执行文件上传
            return storageClient.upload_file(file.getContent(), file.getExt(), metaList);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 图片下载
     *
     * @param groupName      组名：文件上传后所在的 storage 组名称，在文件上传成功后有storage 服务器返回，需要客户端自行保存。
     * @param remoteFileName 虚拟磁盘路径/数据两级目录/文件名
     * @return {@link InputStream} 文件流
     */
    public static InputStream downFile(String groupName, String remoteFileName) {
        ByteArrayInputStream byteArrayInputStream = null;
        try {
            //获取StorageClient对象
            StorageClient storageClient = getStorageClient();
            //根据组名 和 文件名 下载图片

            //参数1:指定组名
            //参数2 :指定远程的文件名
            byte[] bytes = storageClient.download_file(groupName, remoteFileName);
            //将字节数组转换成字节输入流
            byteArrayInputStream = new ByteArrayInputStream(bytes);
            return byteArrayInputStream;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (byteArrayInputStream != null) {
                    byteArrayInputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }


    /**
     * 图片删除
     *
     * @param groupName      组名
     * @param remoteFileName 文件存储完整名
     */
    public static void deleteFile(String groupName, String remoteFileName) {
        try {
            //获取StorageClient对象
            StorageClient storageClient = getStorageClient();
            int i = storageClient.delete_file(groupName, remoteFileName);
            if (i == 0) {
                log.info("删除成功");
            } else {
                log.info("删除失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据组名获取组的信息
     *
     * @param groupName 组名
     * @return {@link StorageServer}
     */
    public static StorageServer getStorages(String groupName) {
        try {
            TrackerClient trackerClient = new TrackerClient();
            //创建tracker server 对象
            TrackerServer trackerServer = trackerClient.getConnection();

            //参数1 指定tracker server 对象
            //参数2 指定组名
            return trackerClient.getStoreStorage(trackerServer, groupName);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 根据文件名和组名获取文件的信息
     *
     * @param groupName      组名
     * @param remoteFileName 文件存储完整名
     * @return {@link FileInfo} 文件的信息
     */
    public static FileInfo getFile(String groupName, String remoteFileName) {
        try {
            //获取StorageClient对象
            StorageClient storageClient = getStorageClient();

            //参数1 指定组名
            //参数2 指定文件的路径
            return storageClient.get_file_info(groupName, remoteFileName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 根据文件组名和文件存储路径获取Storage服务的IP、端口信息
     *
     * @param groupName      组名
     * @param remoteFileName 文件存储完整名
     * @return {@link ServerInfo} 组信息的数组信息
     */
    public static ServerInfo[] getServerInfo(String groupName, String remoteFileName) {
        try {
            //创建tracker client对象
            TrackerClient trackerClient = new TrackerClient();
            //创建tracker server 对象
            TrackerServer trackerServer = trackerClient.getConnection();
            //获取服务信息
            return trackerClient.getFetchStorages(trackerServer, groupName, remoteFileName);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;

    }


    /**
     * 获取tracker 的ip和端口的信息
     *
     * @return http://47.102.136.26:8080
     */
    public static String getTrackerUrl() {
        try {
            //3.创建tracker client对象
            TrackerClient trackerClient = new TrackerClient();
            //4.创建tracker server 对象
            TrackerServer trackerServer = trackerClient.getConnection();
            //tracker 的ip的信息
            String hostString = trackerServer.getInetSocketAddress().getHostString();

            //http://192.168.211.132:8080/group1/M00/00/00/wKjThF1aW9CAOUJGAAClQrJOYvs424.jpg img
            int gTrackerHttpPort = ClientGlobal.getG_tracker_http_port();
            return "http://" + hostString + ":" + gTrackerHttpPort;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取TrackerServer
     * @return {@link TrackerServer}
     * @throws IOException IO异常
     */
    private static TrackerServer getTrackerServer() throws IOException {
        //创建TrackerClient对象
        TrackerClient trackerClient = new TrackerClient();
        //通过TrackerClient获取TrackerServer对象
        return trackerClient.getConnection();
    }


    /**
     * 获取 StorageClient
     * @return {@link StorageClient}
     * @throws IOException IO异常
     */
    private static StorageClient getStorageClient() throws IOException {
        //获取TrackerServer
        TrackerServer trackerServer = getTrackerServer();
        //通过TrackerServer创建StorageClient
        return new StorageClient(trackerServer,null);
    }
}
